#!/usr/bin/env bash

requirements_find_osx_brew()
{
  if
    __rvm_which brew >/dev/null 2>&1
  then
    return 0
  else
    \typeset __binary
    for __binary in ~/homebrew/bin/brew ~/.homebrew/bin/brew /usr/local/bin/brew
    do
      if
        [[ -f "${__binary}" && -s "${__binary}" && -x "${__binary}" ]]
      then
        PATH="$PATH:${__binary%/*}"
        return 0
      fi
    done
    return 1
  fi
}

requirements_osx_brew_version_list()
{
  if __rvm_which $1 >/dev/null
  then $1 --version 2>/dev/null | __rvm_sed -n -e '1{s/^.* //; p;}'
  fi
  __rvm_ls -1 $( brew --cellar )/$1/ 2>/dev/null
}

requirements_osx_brew_lib_installed_prefix_check()
{
  brew_lib_prefix="$( brew --prefix "$1" 2>/dev/null )" &&
  [[ -n "${brew_lib_prefix}" && -d "${brew_lib_prefix}" ]] ||
  return $?
}

requirements_osx_brew_lib_installed()
{
  \typeset brew_lib_prefix

  # Test for older versions of Homebrew before adding the `--formula` flag.
  brew_version=$( brew --version | awk 'NR==1 { print $2 }' )
  if __rvm_version_compare $brew_version -ge 2.5.7
  then brew_ls_flags="--formula"
  fi

  brew list -1 $brew_ls_flags | __rvm_grep "^${1}$" >/dev/null &&
  requirements_osx_brew_lib_installed_prefix_check "$1" ||
  return $?
}

requirements_osx_brew_lib_available()
{
  brew search | __rvm_grep "^${1}$" >/dev/null || return $?
}

requirements_osx_brew_libs_error()
{
    rvm_warn "There were package ${1} errors, make sure to read the log.

Try \`brew tap --repair\` and make sure \`brew doctor\` looks reasonable.

Check Homebrew requirements https://docs.brew.sh/Installation"
}

requirements_osx_brew_libs_install()
{
  brew install "$@" --force ||
  {
    \typeset ret=$?

    requirements_osx_brew_libs_error "installation"

    return $ret
  }
}

requirements_osx_brew_libs_remove()
{
  brew remove "$@" ||
  {
    \typeset ret=$?

    requirements_osx_brew_libs_error "removal"

    return $ret
  }
}

requirements_osx_brew_check_custom()
{
  brew tap | __rvm_grep "$1" >/dev/null || __rvm_add_once packages_custom "$1"
}

requirements_osx_brew_install_custom()
{
  \typeset __tap
  for __tap
  do brew tap "${__tap}" || return $?
  done
}

requirements_osx_brew_libs_outdated_filter()
{
  \typeset IFS
  IFS="|"
  brew outdated --quiet | __rvm_grep -E "$*"
}

requirements_osx_brew_libs_try_upgrade()
{
  (( rvm_autolibs_flag_number > 0 )) || return 0

  \typeset -a outdated_libs
  __rvm_read_lines outdated_libs <(
    requirements_osx_brew_libs_outdated_filter "$@"
  )
  if
    (( ${#outdated_libs[@]} ))
  then
    rvm_requiremnts_fail_or_run_action 2 \
      "Homebrew libs '${outdated_libs[*]}' require update - skipping." \
      brew upgrade "${outdated_libs[@]}" ||
      return $?
  fi
}

requirements_osx_brew_libs_set_path()
{
  \typeset brew_lib brew_lib_prefix

  for brew_lib
  do
    if requirements_osx_brew_lib_installed_prefix_check "${brew_lib}"
    then __rvm_add_to_path prepend "${brew_lib_prefix}/bin"
    fi
  done
  rvm_debug "PATH=$PATH"
}

requirements_osx_brew_libs_configure()
{
  \typeset package brew_lib brew_lib_prefix
  package="$1"
  shift

  for brew_lib
  do
    if requirements_osx_brew_lib_installed_prefix_check "${brew_lib}"
    then __rvm_update_configure_opt_dir "${package}" "${brew_lib_prefix}"
    fi
  done
}

requirements_osx_brew_after()
{
  (( ${#packages_installed[@]} == 0 )) ||
  requirements_osx_brew_libs_try_upgrade "${packages_installed[@]}" || return $?

  requirements_osx_brew_libs_set_path       "${brew_libs[@]}"       || return $?
  requirements_osx_brew_libs_configure "$1" "${brew_libs_conf[@]}"  || return $?

  case "$1" in
    (jruby*) true ;;
    (*) requirements_osx_brew_after_update_certs_openssl "$1" ;;
  esac

  unset brew_libs brew_libs_conf brew_openssl_package
}

requirements_osx_brew_after_update_certs_openssl()
{
  \typeset brew_lib_prefix
  if
    requirements_osx_brew_lib_installed_prefix_check "$brew_openssl_package" &&
    [[ -x "${brew_lib_prefix}/bin/openssl" ]]
  then
    requirements_osx_update_openssl_cert "${brew_lib_prefix}/bin/openssl" || return $?
  else
    rvm_requiremnts_fail_always 2 \
      "Somehow it happened there is no executable 'openssl',
run 'brew doctor' and make sure latest '$brew_openssl_package' is installed properly." ||
      return 12 # passing by 127 could be read as missing rvm.
  fi
}

requirements_osx_brew_libs_default_check_gcc()
{
  if
    requirements_detect_installed gcc gcc@8 gcc@7 gcc@6 gcc@5 gcc@4.9
  then
    case "${packages_installed[*]}" in
      (*gcc*)         export CC="$(brew --prefix gcc        )/bin/gcc-8" ;;
      (*gcc@8*)       export CC="$(brew --prefix gcc@8      )/bin/gcc-8" ;;
      (*gcc@7*)       export CC="$(brew --prefix gcc@7      )/bin/gcc-7" ;;
      (*gcc@6*)       export CC="$(brew --prefix gcc@6      )/bin/gcc-6" ;;
      (*gcc@5*)       export CC="$(brew --prefix gcc@5      )/bin/gcc-5" ;;
      (*gcc@4.9*)     export CC="$(brew --prefix gcc@4.9    )/bin/gcc-4.9" ;;
      (*)             return 1 ;;
    esac
  else
    return $?
  fi
}

requirements_osx_brew_libs_default_add_gcc_v_auto()
{
  # Install gcc from brew only for macOS earlier then Mojave (10.14)
  if __rvm_version_compare "${_system_version}" -lt 10.14
  then
    if __rvm_version_compare "${_system_version}" -ge 10.10
    then requirements_osx_brew_libs_default_add_gcc_v 6.0
    else requirements_osx_brew_libs_default_add_gcc_v 4.9
    fi
  fi
}

requirements_osx_brew_libs_default_add_gcc_v()
{
  case "$1" in
    (4.9) requirements_osx_brew_libs_default_add_gcc "$2" gcc-4.9 gcc@4.9     ;;
    (5.0) requirements_osx_brew_libs_default_add_gcc "$2" gcc-5.0 gcc@5       ;;
    (6.0) requirements_osx_brew_libs_default_add_gcc "$2" gcc-6.0 gcc@6       ;;
    (7.0) requirements_osx_brew_libs_default_add_gcc "$2" gcc-7.0 gcc@7       ;;
    (8.0) requirements_osx_brew_libs_default_add_gcc "$2" gcc-8.0 gcc@8       ;;
    (*)
      rvm_error "Do not know how to check/install gcc '$1'."
      return 1
      ;;
  esac
}

requirements_osx_brew_libs_default_add_gcc()
{
  if [[ -n "$1" ]] && __rvm_which "$1" >/dev/null
  then true
  else
    export CC="$2"
    if __rvm_which "$2" >/dev/null
    then true
    else
      if [[ -z "${3:-}" ]]
      then false           # no package known and binary not found
      else
        if [[ -z "$(brew --prefix $3 2>/dev/null)" ]]
        then
          rvm_error "We don't know how to install <code>$3</code>"
          rvm_log "Try to run <code>brew install $3</code> and re-run the same rvm command afterwards."
          false
        else
          export CC="$(brew --prefix $3 2>/dev/null || brew --prefix)/bin/$2"
          brew_libs+=( "$3" )
        fi
      fi
    fi
  fi
}

requirements_osx_brew_define_gcc()
{
  # Old gcc46 but it will most likely not work on OSX 10.10+
  if __rvm_version_compare "${_system_version}" -ge 10.10
  then
    undesired_check gcc46
  fi

  \typeset selected_compiler="$( __rvm_selected_compiler )"

  case "${selected_compiler:-}" in
    ("")
      case "$1" in
        (rbx-2*|rubinius-2*)
            brew_libs_conf+=( llvm@3.5 )
            ;;

        (rbx-3*|rubinius-3*|rbx*head|rubinius*head)
            requirements_check git openssl readline libyaml gdbm llvm@5
            rvm_configure_flags+=( --llvm-config="$(brew --prefix llvm@5)/bin/llvm-config" )
            ;;

        (truffleruby*)
            ;;

        (*)
          # Install gcc from brew only for macOS earlier then Mojave (10.14)
          if __rvm_version_compare "${_system_version}" -lt 10.14
          then
            __ruby_clang_ok "$1" ||
            requirements_osx_brew_libs_default_check_gcc ||
            requirements_osx_brew_libs_default_add_gcc_v_auto ||
            return $?
          fi
          ;;
      esac
      ;;

    (*gcc-4.9|*gcc-5|*gcc-6|*gcc-7|*gcc-8|*gcc)
      requirements_osx_brew_libs_default_add_gcc_v ${selected_compiler##*-} "${selected_compiler}" || return $?
                                                   # version                # full_path
      ;;

    (*)
      rvm_warn "We don't know how to ensure that selected compiler '${selected_compiler}' exists."
      ;;
  esac
}

requirements_osx_brew_define_openssl()
{
  # OpenSSL version depends on the version of Ruby being installed
  undesired_check openssl098

  case "$1" in
    (ruby-2.3*|ruby-2.2*|ruby-2.1*|ruby-2.0*|ruby-1.9*|ruby-1.8*)
      brew_openssl_package="openssl"
      ;;

    (ree-1.8*)
      brew_openssl_package="openssl"
      ;;

    (rbx-1*|rbx-2*)
      brew_openssl_package="openssl"
      ;;

    (truffleruby*)
      brew_openssl_package="openssl"
      ;;

    (*)
      brew_openssl_package="openssl@1.1"
      ;;
  esac

  brew_libs_conf+=( "$brew_openssl_package" )
}

requirements_osx_brew_libs_default()
{
  brew_libs=(
    autoconf automake libtool pkg-config coreutils
  )
  brew_libs_conf=(
    libyaml libksba readline zlib
  )

  requirements_osx_brew_define_gcc "$1"
  requirements_osx_brew_define_openssl "$1"

  requirements_check "${brew_libs[@]}" "${brew_libs_conf[@]}" || return $?
}

requirements_osx_brew_define()
{
  case "$1" in
    (rvm)
      true
      ;;

    (jruby*)
      requirements_check make

      if
        is_head_or_disable_binary "$1"
      then
        __rvm_which git >/dev/null || requirements_check git
        case $( jruby_installation_method  "$1" ) in
          mvn) requirements_check_custom_after mvn=maven ;;
        esac
      fi
      requiremnts_osx_java_fail  || return $?
      ;;

    (ir*)
      __rvm_which mono >/dev/null 2>&1 || return $?
      ;;

    (opal)
      requirements_check node
      ;;

    (truffleruby*)
      requirements_osx_brew_libs_default "$1"
      ;;

    (ruby*head)
      __rvm_which git >/dev/null || requirements_check git
      requirements_osx_brew_libs_default "$1"
      requirements_version_minimal autoconf 2.67
      ;;

    (*-head)
      __rvm_which git >/dev/null || requirements_check git
      requirements_osx_brew_libs_default "$1"
      ;;

    (*)
      requirements_osx_brew_libs_default "$1"
      ;;
  esac
}

__CLT_version_at_least()
{
  \typeset __version="$(
    pkgutil --pkg-info com.apple.pkg.DeveloperToolsCLI 2>/dev/null | __rvm_awk '$1~/version:/{print $2}'
  )"
  [[ -n "${__version}" ]] || __version="$(
    pkgutil --pkg-info com.apple.pkg.CLTools_Executables 2>/dev/null | __rvm_awk '$1~/version:/{print $2}'
  )"
  [[ -n "${__version}" ]] ||return $?
  __rvm_version_compare "${__version}" -ge "$1" || return $?
}

requirements_osx_brew_update_system()
{
  if
    __rvm_version_compare "${_system_version}" -ge 10.7
  then
    __rvm_detect_xcode_version_at_least 4.6.2 ||
    __CLT_version_at_least 4.6.0 ||
    {
      \typeset ret=$?
      rvm_error "
Xcode version older than 4.6.2 installed, download and install newer version from:

    http://connect.apple.com

After installation open Xcode, go to Downloads and install Command Line Tools.
"
      return $ret
    }
  fi
  brew update ||
  {
    \typeset ret=$?
    rvm_error "Failed to update Homebrew, follow instructions at

    https://docs.brew.sh/Common-Issues

and make sure \`brew update\` works before continuing."
    return $ret
  }
}

requirements_osx_brew_install_brew_setup()
{
  if
    __rvm_version_compare "${_system_version}" -ge 10.5
  then
    homebrew_repo="Homebrew/brew"
    homebrew_installer="https://raw.githubusercontent.com/Homebrew/install/master/install"
    homebrew_name="Homebrew"
  else
    homebrew_repo="mistydemeo/tigerbrew"
    homebrew_installer="https://raw.githubusercontent.com/mistydemeo/tigerbrew/go/install"
    homebrew_name="Tigerbrew"
  fi
  if
    (( UID == 0 )) && [[ -z "${SUDO_USER:-}" ]]
  then
    rvm_error "Requested installation of ${homebrew_name} but the process is running as 'root', make sure to run with 'sudo' from normal user and try again."
    return 1
  fi
  homebrew_home_default="/usr/local"
  printf "%b" "About to install ${homebrew_name} in the default location \`$homebrew_home_default\`.\n
It is possible to select a custom location, however it is not recommended and some things might not work.
You should do it only if you do not have write rights to \`$homebrew_home_default\`.

Press ENTER to install ${homebrew_name} in the default location \`$homebrew_home_default\`
or type a custom path (needs to be writable for the current user)\n: "
  read homebrew_home || return $?
  rvm_debug "homebrew_home=${homebrew_home:=$homebrew_home_default}"
}

requirements_osx_brew_install_brew_install()
{
  if
    [[ "${homebrew_home}" == "${homebrew_home_default}" ]]
  then
    rvm_debug "Default homebrew installation from: $homebrew_installer"
    if [[ -n "${SUDO_USER:-}" ]]
    then su - ${SUDO_USER} -c "ruby -e \"$(curl -fsSL $homebrew_installer)\"" || return $?
    else ruby -e "$(curl -fsSL $homebrew_installer)" || return $?
    fi
  else
    rvm_debug "Simplified homebrew installation from: https://github.com/${homebrew_repo}/tarball/master"
    mkdir -p "${homebrew_home}" || return $?
    __rvm_curl https://github.com/${homebrew_repo}/tarball/master | tar xz --strip 1 -C "${homebrew_home}"
    __rvm_check_pipestatus ${PIPESTATUS[@]} ${pipestatus[@]} || return $?
    chmod +x "${homebrew_home}/bin/brew" # just in case
    if [[ -n "${SUDO_USER:-}" ]]
    then chown -R ${SUDO_USER} "${homebrew_home}"
    fi
  fi
  PATH="$PATH:${homebrew_home}/bin"
}

requirements_osx_brew_install_brew()
{
  \typeset homebrew_home_default homebrew_home homebrew_repo homebrew_installer homebrew_name

  requirements_osx_brew_install_brew_setup   || return $?
  requirements_osx_brew_install_brew_install || return $?
}

requirements_osx_brew_ensure_brew_available()
{
  __rvm_which brew >/dev/null ||
  {
    rvm_requiremnts_fail_or_run_action 2 \
      "Requested installation with Homebrew libs, but Homebrew is not available." \
      requirements_osx_brew_install_brew || return $?
  }

  __rvm_which brew >/dev/null ||
  {
    \typeset __result=$?
    rvm_error "\
Something went wrong during Homebrew installation,
can not find 'brew' command, please report a bug: https://github.com/rvm/rvm/issues"
    return $__result
  }
}

requirements_osx_brew_ensure_brew_can_install()
{
  # only check for 3+ (packages install, enabled)
  (( rvm_autolibs_flag_number > 2 )) || return 0

  \typeset __celar_path
  __celar_path="$(brew --cellar)"
  if
    [[ ! -w "${__celar_path%/*}/bin" ]]
  then
    rvm_error "ERROR: '${__celar_path%/*}/bin' is not writable - it is required for Homebrew, try 'brew doctor' to fix it!"
    return 1
  elif
    [[ ! -w "${__celar_path}" && -e "${__celar_path}" ]]
  then
    rvm_error "ERROR: '${__celar_path}' is not writable - it is required for Homebrew, try 'brew doctor' to fix it!"
    return 1
  else
    rvm_debug "brew seems to be writable"
  fi
}

requirements_osx_brew_before()
{
  requirements_osx_brew_ensure_brew_available   || return $?
  requirements_osx_brew_ensure_brew_can_install || return $?
}
